#pragma once

#include <iostream>
#include <cerrno>
#include "Connection.hpp"
#include "Protocol.hpp"
#include "Calculate.hpp"
#include "Log.hpp"

using namespace Protocol;
using namespace CalculateNS;

const static int buffer_size = 1024;

class HandlerConnection
{
public:
    static void HandlerRequest(Connection *conn)
    {
        string &inbuffer = conn->Inbuffer();
        string message;      // 表示一个符合协议的完整报文
        Calculate calculate; // 负责业务处理
        Factory factory;
        auto req = factory.BuildRequest();
        // 1.明确报文边界，解决粘包问题
        while (Decode(inbuffer, &message))
        {
            // message 一定是一个完整的报文,符合协议的
            // 2. 反序列化
            if (!req->deserialize(message))
                continue;
            // 3. 业务处理
            auto resp = calculate.Cal(req);
            // 4. 对响应进行序列化
            string responseStr;
            resp->serialize(&responseStr);
            // 5. 封装完整报文
            responseStr = Encode(responseStr);
            // 6. 将应答全部追加到outbuffer中
            conn->AddOutBuffer(responseStr);
        }
        // 考虑发送的问题
        if (!conn->OutBufferEmpty())
        {
            conn->_sender(conn); // 对写事件，直接发
        }
    }

    // 在这里读取的时候不关心数据是什么格式，协议是什么样子
    // 只负责把本轮数据读取完毕，把读到的字节流数据交给上层————由上层分析处理
    static void Recver(Connection *conn)
    {
        errno = 0;
        // 读取流程
        char buffer[1024];
        while (1)
        {
            ssize_t n = recv(conn->SockFd(), buffer, sizeof(buffer) - 1, 0); // 非阻塞读取
            if (n > 0)
            {
                buffer[n] = 0;
                conn->AddInBuffer(buffer);
            }
            else
            {
                cout << "..........................." << endl;
                if (errno == EAGAIN)
                    break;
                else if (errno == EINTR)
                    continue;
                else
                {
                    // 真正的读取错误
                    conn->_excepter(conn); // 直接回调自己的异常处理就可以了
                    return;
                }
            }
        }
        cout << "sockfd# " << conn->SockFd() << ":\n " << conn->Inbuffer() << endl;
        // 读取完毕,尝试分析处理报文
        HandlerRequest(conn);
    }
    static void Sender(Connection *conn)
    {
        errno = 0;
        string &outbuffer = conn->OutBuffer();
        while (true)
        {
            ssize_t n = send(conn->SockFd(), outbuffer.c_str(), outbuffer.size(), 0);
            if (n >= 0)
            {
                outbuffer.erase(0, n); // 把已经发的数据移除(可能没发完)
                if (outbuffer.empty())
                    break;
            }
            else
            {
                // 发送失败
                if (errno == EAGAIN)
                    break;
                if (errno == EINTR)
                    continue;
                else
                {
                    conn->_excepter(conn);
                    return;
                }
            }
        }
        // 本轮发满了，但是数据可能没发完(操作系统 socket 发送缓冲区满了)
        // 开启对conn->Sockfd() EPOLLOUT的关心
        if (!conn->OutBufferEmpty()) // 说明没有发完
        {
            conn->_R->EnableReadWrite(conn->SockFd(), true, true);
        }
        else
        {
            conn->_R->EnableReadWrite(conn->SockFd(), true, false); // 关掉写事件关心
        }
    }
    static void Excepter(Connection *conn)
    {
        lg.LogMessage(Info, "connection erase done, who: %d\n",conn->SockFd());
        errno = 0;
        // 从epoll中移除对conn->Sockfd的关心
        // unorder_map 移除 conn
        conn->_R->RemoveConnection(conn->SockFd());
        // 关闭conn->sockfd
        conn->Close();
        // delete conn
        delete conn;
    }

private:
};
